/********************************************
* Copyrigt (C) rumi
* Module: drv_onewire.c
*********************************************/
#include "drv_onewire.h"

static void OneWire_Delay(OneWire_Node *lDeivce,uint16_t delay)
{
	for (uint16_t i = 0; i < lDeivce->Delay; i++);
}

uint8_t Bus_OneWire_BusOff(OneWire_Node *lDeivce)
{
    Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
    OneWire_Delay(lDeivce,100);
    Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);

    if(lDeivce->CurrentSpeed == E_LOW_SPEED){
        OneWire_Delay(lDeivce,500);
        Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
        OneWire_Delay(lDeivce,70);
    }
    else{
        OneWire_Delay(lDeivce,70);
        Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
        OneWire_Delay(lDeivce,8);
    }

    for(int i=0; i<5; i++){
        if(Drv_IO_Control(lDeivce->OneWireIO,E_PIN_READ,0) == 0){
            OneWire_Delay(lDeivce,200);
            return 1;
        }
    }
    return 0;
}


void Bus_OneWire_SendByte(OneWire_Node *lDeivce,uint8_t data)
{
    Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);

    for(uint8_t count=0;count<8;count++)
	{
		if((data&(0x01<<count))==0){
			if (lDeivce->CurrentSpeed == E_HIGH_SPEED){
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);
				OneWire_Delay(lDeivce,10);
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
				OneWire_Delay(lDeivce,10);
			}else{
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);
				OneWire_Delay(lDeivce,100);
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
				OneWire_Delay(lDeivce,10);
			}
		}else{
			if (lDeivce->CurrentSpeed == E_HIGH_SPEED){
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);
				OneWire_Delay(lDeivce,1);
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
				OneWire_Delay(lDeivce,100);
			}else{
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);
				OneWire_Delay(lDeivce,10);
				Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
				OneWire_Delay(lDeivce,100);
			}
		}
	}
}

uint8_t Bus_OneWire_GetByte(OneWire_Node *lDeivce)
{
    uint8_t data=0;
    for(uint8_t count=0;count<8;count++){
		Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,low);
		
		if (lDeivce->CurrentSpeed == E_HIGH_SPEED){
			OneWire_Delay(lDeivce,1);
		}else{
			OneWire_Delay(lDeivce,8);
		}
		
		Drv_IO_Control(lDeivce->OneWireIO,E_PIN_WRITE,high);
		
		if (lDeivce->CurrentSpeed == E_HIGH_SPEED){
			OneWire_Delay(lDeivce,1);
		}else{
			OneWire_Delay(lDeivce,10);
		}
		
		if(Drv_IO_Control(lDeivce->OneWireIO,E_PIN_READ,0) == 1){
			data |= (0x01<<count);
		}
		
		if (lDeivce->CurrentSpeed == E_HIGH_SPEED){
			OneWire_Delay(lDeivce,10);
		}else{
			OneWire_Delay(lDeivce,60);
		}
	}
    return data;
}

uint8_t Bus_OneWire_Turn_HighSpeed(OneWire_Node *lDeivce)
{
	uint8_t lRet=0;

	if ((lDeivce->CurrentSpeed == E_LOW_SPEED)&&(lDeivce->TargetSpeed == E_HIGH_SPEED))
	{
		Bus_OneWire_SendByte(lDeivce,0x3C);	// trun HighSpeed
		lDeivce->CurrentSpeed = E_HIGH_SPEED;
		lRet = 1;	
	}

	if ((Bus_OneWire_BusOff(lDeivce)) != 1)
	{
		lDeivce->CurrentSpeed = E_LOW_SPEED;
		lRet = 0;
	}
	return lRet;

}

uint8_t Drv_OneWire_Control(OneWire_Node *lDeivce,uint8_t type,uint8_t data)
{
	uint8_t lRet=0;
	switch(type){
		case E_ONEWIRE_INIT:
			break;
		case E_ONEWIRE_TURN_HIGH_SPEED:
			Bus_OneWire_Turn_HighSpeed(lDeivce);
			break;
		case E_ONEWIRE_GET_BYTE:
			lRet = Bus_OneWire_GetByte(lDeivce);
			break;
		case E_ONEWIRE_SEND_BYTE:
			Bus_OneWire_SendByte(lDeivce,data);
			break;
		default:
			break;
	}
	return lRet;
}

/********************************************
 * End of file
*********************************************/